/***************************************************************************
 *   This is a part of the NextCAD Web APP.                                *
 *   Copyright (C) AMCAX, All rights reserved.                             *
 ***************************************************************************/

// import { Alert, Button } from 'antd';
import { NonDialogPickableCommandForm } from '@app-cad/common/components/command-form/pickable';
import { useCommand } from '@app-cad/common/hooks/useCommand';
import { useTools } from '@app-cad/common/hooks/useTools';
import { RJSFSchema } from '@rjsf/utils';
import { omitBy } from 'lodash';
import { useEffect, useMemo } from 'react';
import ReverseIconWidget from '../../../../../common/RJSFWidgets/ReverseIconWidget';
import {
  angle2ForCounterdrilled,
  diameter2ForCounterdrilled,
  diameter3,
  drilledOption,
  getMinimumCommonFields,
  getMinimumCommonParamsForCommand,
  hatDepthForCounterdrilled,
  initFormDataWithProps,
  locationOptionForCounterdrilled,
  minimumFormValidation,
} from './common-fields';
import { commonUiSchema } from './common-ui-schema';
import { ChildHoleProps, MinCommonFormData, MinCommonParams } from './types';

type FormData = {
  type?: string;
  locationOption?: 'bottom' | 'middle';
  diameter2?: number;
  hatDepth?: number;
  angle2?: number;
  drilledOption?: 'withoutSunkDiameter' | 'withSunkDiameter';
  diameter3?: number;
} & MinCommonFormData;

type Params = {
  type?: string;
  locationOption?: 'bottom' | 'middle';
  diameter2?: number;
  hatDepth?: number;
  angle2?: number;
  drilledOption?: 'withoutSunkDiameter' | 'withSunkDiameter';
  diameter3?: number;
} & MinCommonParams;

export function CounterdrilledHole({
  onClose,
  editDxid,
  props,
  formData,
  setFormData,
}: ChildHoleProps<Params, FormData>) {
  const schema: RJSFSchema = useMemo(() => {
    const properties = omitBy(
      {
        ...getMinimumCommonFields(formData),
        locationOption: locationOptionForCounterdrilled,
        drilledOption,
        diameter2: diameter2ForCounterdrilled,
        angle2: angle2ForCounterdrilled,
        hatDepth: hatDepthForCounterdrilled,
        diameter3:
          formData.drilledOption === 'withSunkDiameter' ? diameter3 : null,
      },
      (val) => val == null,
    );
    return {
      type: 'object',
      properties,
    } as RJSFSchema;
  }, [formData.bottomType, formData.mode, formData.drilledOption]);
  const { picker } = useTools();

  useEffect(() => {
    preview();
  }, [formData]);

  useEffect(() => {
    if (props == null) {
      setFormData({
        ...formData,
        mode: formData.mode || 'distance',
        locationOption: formData.locationOption || 'bottom',
        drilledOption: formData.drilledOption || 'withoutSunkDiameter',
      });
      return;
    }

    const { params } = props;
    const { locationOption, diameter2, hatDepth, drilledOption, diameter3 } =
      params;

    initFormDataWithProps(params, initEditDependency, picker).then((minForm) =>
      setFormData({
        ...minForm,
        locationOption: locationOption || 'bottom',
        diameter2,
        hatDepth,
        drilledOption: drilledOption || 'withoutSunkDiameter',
        diameter3,
      }),
    );
  }, [editDxid]);

  const isFormDataValid = () => {
    const isDepthValidForAngleDiameterOption =
      formData.diameter2 !== null &&
      formData.angle2 !== null &&
      formData.hatDepth !== null &&
      (formData.diameter2 - formData.diameter) /
        2 /
        Math.tan((formData.angle2 / 2) * (Math.PI / 180)) <
        formData.depth - formData.hatDepth;
    const isDiameter3Valid =
      formData.diameter2 !== null &&
      formData.diameter3 !== null &&
      formData.diameter3 > formData.diameter &&
      formData.diameter3 < formData.diameter2;

    return (
      minimumFormValidation(formData) &&
      isDepthValidForAngleDiameterOption &&
      (formData.drilledOption !== 'withSunkDiameter' || isDiameter3Valid)
    );
  };

  const checkAndFinishDraw = async () => {
    if (!isFormDataValid()) {
      return;
    }

    await execute(false);
    onClose();
  };

  const { initEditDependency, initingEdit, clear, confirmCommand, isLoading } =
    useCommand('cmd-holes', {
      commandName: 'CreateHoles',
      editDxid,
      dependencies: props?.params ? [props.params.base] : [],
      onClose,
      finishDraw: checkAndFinishDraw,
    });

  const execute = (preview: boolean) => {
    return confirmCommand(
      {
        a: {
          type: 'Counterdrilled',
          ...getMinimumCommonParamsForCommand(formData),
          locationOption: formData.locationOption,
          diameter2: formData.diameter2,
          hatDepth: formData.hatDepth,
          angle2: formData.angle2,
          drilledOption: formData.drilledOption,
          diameter3: formData.diameter3,
        } as Params,
      },
      preview,
    );
  };

  const preview = async () => {
    if (!isFormDataValid()) {
      clear();
      return;
    }

    await execute(true);
  };

  const finalFormData = useMemo(
    () => ({
      ...formData,
    }),
    [formData],
  );

  return (
    <NonDialogPickableCommandForm
      disabled={initingEdit}
      onCancel={onClose}
      schema={schema}
      submitLoading={isLoading}
      formData={finalFormData}
      widgets={{
        reverseIcon: ReverseIconWidget,
      }}
      onChange={(v) => {
        setFormData(v);
      }}
      submitText='完成'
      onSubmit={checkAndFinishDraw}
      extraUiSchema={{
        ...commonUiSchema,
        diameter2: {
          'ui:placeholder': '大于主直径',
        },
        hatDepth: {
          'ui:placeholder': '小于主深度',
        },
        angle2: {
          'ui:placeholder': '0° ～ 180°',
        },
        diameter3: {
          'ui:placeholder': '主径 ～ 孔径',
        },
      }}
      isFormDataValid={isFormDataValid()}
    />
  );
}
